package zdream.pmfield.test.stage.effect;

import org.junit.Before;
import org.junit.Test;

import zdream.pmfield.data.foe.Foe;
import zdream.pmfield.data.foe.MoveTemplate;
import zdream.pmfield.stage.StageBuilderForTest;
import zdream.pmfield.stage.StageWrapper;
import zdream.pmfield.stage.message.ActionStartMessage;
import zdream.pmfield.stage.message.AttackMessage;
import zdream.pmfield.stage.message.FoeAddBuffMessage;
import zdream.pmfield.stage.message.FoeRemoveBuffMessage;
import zdream.pmfield.stage.message.TurnStartMessage;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.test.utils.ResourceConstant;
import zdream.pmfield.test.utils.StageConstant;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-12-19
 * @since 0.0.1
 */
public class FixatedBuffCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.load();
		storage.loadMovesInResource(ResourceConstant.RES_PATH_TEST_MOVES_JSON);
	}

	@Test
	public void testFixatedEffect() {
		MoveTemplate fixatedMove = storage.findMoveById(10000051, 1);
		assertEquals("自己热衷", fixatedMove.name);
		MoveTemplate physicalMove = storage.findMoveById(10000020, 1);
		assertEquals("物理的", physicalMove.name);

		Foe foe1 = Foe.builder(storage.findFoeById(4))
				.withLevel(30)
				.withMove(fixatedMove)
				.withMove(physicalMove)
				.build();
		Foe foe2 = Foe.builder(storage.findFoeById(1))
				.withLevel(30)
				.withMove(physicalMove)
				.build();

		final StageWrapper wrapper = StageBuilderForTest.builder()
				.putFoeToOneSide(foe1)
				.putFoeToAnotherSide(foe2)
				.withStorage(storage)
				.disableDistanceCheck()
				.buildWrapper();

		System.out.println("TEST 1: apply fixated");
		wrapper.printBeforeHandleMessage();
		wrapper.onDefaultActionRequest();

		wrapper.runUntil(TurnStartMessage.class, message -> message.foe.foe == foe1);
		wrapper.runUntil(ActionStartMessage.class, message -> {
			assertTrue(message.action.isForAttack());
			assertEquals(foe1, message.action.asAttack().foe.foe);
			assertEquals(fixatedMove, message.action.asAttack().move.move);
			return true;
		});
		wrapper.runUntil(AttackMessage.class, message -> {
			assertEquals(1, message.report.items.size());
			assertEquals(0, 1, message.report.items.get(0).typeFixed);
			return true;
		});
		wrapper.runUntil(FoeAddBuffMessage.class, message -> {
			assertTrue(message.success);
			assertEquals(foe1, message.foe.foe);
			assertTrue(message.buff.is(StageConstant.BUFF_FIXATED));
			return true;
		});

		System.out.println("TEST 2: fixated 状态我方增伤");
		wrapper.runUntil(TurnStartMessage.class, message -> message.foe.foe == foe1);
		wrapper.runUntil(ActionStartMessage.class, message -> {
			assertTrue(message.action.isForAttack());
			assertEquals(foe1, message.action.asAttack().foe.foe);
			assertEquals(fixatedMove, message.action.asAttack().move.move);
			return true;
		});
		wrapper.runUntil(AttackMessage.class, message -> {
			assertEquals(1, message.report.items.size());
			assertEquals(0.00001, 1.3, message.report.items.get(0).attackFixed);
			return true;
		});
		wrapper.runUntil(FoeRemoveBuffMessage.class, message -> {
			assertEquals(foe1, message.foe.foe);
			assertTrue(message.buff.is(StageConstant.BUFF_FIXATED));
			return true;
		});
		wrapper.runUntil(FoeAddBuffMessage.class, message -> {
			assertTrue(message.success);
			assertEquals(foe1, message.foe.foe);
			assertTrue(message.buff.is(StageConstant.BUFF_FIXATED));
			return true;
		});

		System.out.println("TEST 3: fixated 状态受到伤害增加");
		wrapper.runUntil(TurnStartMessage.class, message -> message.foe.foe == foe2);
		wrapper.runUntil(AttackMessage.class, message -> {
			assertEquals(1, message.report.items.size());
			assertEquals(0.00001, 0.8, message.report.items.get(0).defenseFixed);
			return true;
		});

		System.out.println("TEST 4: 使用其它技能会让热衷失效");
		wrapper.runUntil(TurnStartMessage.class, message -> message.foe.foe == foe1);
		wrapper.onActionRequest(wrapper.createDefaultController().withMove(physicalMove), foe1);
		wrapper.runUntil(AttackMessage.class, message -> {
			assertEquals(1, message.report.items.size());
			assertEquals(foe1, message.report.action.asAttack().foe.foe);
			assertEquals(0, 1, message.report.items.get(0).attackFixed);
			return true;
		});
	}
}
